package manager;

/**
 * Cette classe représente les solutions du problème. Ces solutions sont représentées
 * par un tableau indiquant l'unité présente sur chaque site (voir Document Technique).
 * Cette classe possède notamment une méthode permettant de permuter les unités de deux sites.
 * 
 * @author BERNARD Arthur, DELAMARCHE Jérôme, PAVAGEAU Max
 *
 */
public class Solution implements Cloneable {
	/**
	 * La véritable représentation de la solution : un tabeau pour connaître l'unité sur chaque site.
	 */
	private int[] solution;
	
	/**
	 * Un constructeur basique pour créer une solution.
	 * 
	 * @param tailleProbleme La taille du problème traité.
	 */
	public Solution(int tailleProbleme) {
		solution = new int[tailleProbleme];
	}
	
	/**
	 * Permet de modifier une des unités présente sur un site.
	 * 
	 * @param site Le site à modifier. 
	 * @param unite L'unité à placer sur ce site.
	 */
	public void setUniteAt(int site, int unite) {
		solution[site - 1] = unite;
	}
	
	/**
	 * Permet de connaître l'unité sur un site.
	 * 
	 * @param site Le site dont on veut connaître l'unité.
	 * @return L'unité sur le site voulu.
	 */
	public int getUniteAt(int site) {
		return solution[site - 1];
	}
	
	/**
	 * Retourne cette solution.
	 * 
	 * @return Le tableau représentant la solution.
	 */
	public int[] getSolution() {
		return solution;
	}
	
	/**
	 * Change la solution.
	 * 
	 * @param newSolution La nouvelle valeur de la solution.
	 */
	public void setSolution(int[] newSolution) {
		solution = newSolution;
	}
	
	/**
	 * Méthode statique qui génère une solution initiale du PAQ.
	 * 
	 * @param taille La taille de la solution désirée.
	 * @return La solution générée.
	 */
	public static Solution getSolutionInit(int taille) {
		Solution solutionInit = new Solution(taille);
		
		//Génération de la solution initiale gloutonne
		for(int i = 0; i < taille; i++) {
			solutionInit.setUniteAt(i+1, i);
		}
		
		return solutionInit;
	}
	
	/**
	 * Permet de permuter deux sites (échanger leurs unités respectives).
	 * 
	 * @param site1 Le premier site à permuter.
	 * @param site2 Le second site à permuter.
	 */
	public void permuterSites(int site1, int site2) {
		int tmp;
		
		tmp = solution[site1 - 1];
		solution[site1 - 1] = solution[site2 - 1];
		solution[site2 - 1] = tmp;
	}
	
	/**
	 * Cette méthode permet de générer aléatoirement une solution dans le voisinage de profondeur voulue
	 * de la solution courante.
	 * 
	 * @param profondeur La profondeur du voisinage.
	 * @return La nouvelle solution générée
	 */
	public Solution getVoisAlea(int profondeur) {
		Solution newSolution = this.clone();
		int nbMouvements = (int)(Math.random()*profondeur) + 1;
		int site1, site2;
		
		int[][] mouvements = new int[nbMouvements][2]; //Permet de mémoriser les mouvements pour ne pas "retourner en arrière"
		
		for(int i = 0; i < nbMouvements; i++) {
			do {
				site1 = (int)(Math.random()*this.solution.length) + 1;
				
				do 
					site2 = (int)(Math.random()*this.solution.length) + 1;
				while(site2 == site1); //On empêche les mouvements inutiles
			} while((i != 0) && (mouvements[i-1][0] == site1) && (mouvements[i-1][1] == site2)); //On empêche le retour en arrière
			
			newSolution.permuterSites(site1, site2);
			mouvements[i][0] = site1;
			mouvements[i][1] = site2;
		}
		
		return newSolution;
	}
	
	/**
	 * Redéfinition de la méthode de Object.
	 */
	public Solution clone() {
		Solution newSolution = null;
		
		try {
			newSolution = (Solution)super.clone();
			newSolution.solution = (int[])solution.clone();
		}
		catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		
		return newSolution;
	}
	
	/**
	 * Redéfinition de la méthode de Object.
	 */
	public String toString() {
		String str = "[";
		
		for(int i = 0; i < solution.length; i++) {
			if(i != solution.length - 1)
				str += (solution[i]+1) + ",";
			else
				str += (solution[i]+1) + "]";
		}
		
		return str;
	}
}
